package com.example.demo.singletonMode;

/**
 * 双检锁式线程安全单例
 * 加锁可以保证在运行过程中，一次最多只有一个线程执行判空并new出实例，但是当多个线程同时调用时，每次都要执行ynchronized同步化方法，
 * 严重影响效率，所以再加一层检查，如果已经被实例过，就直接返回。
 *
 * 并发编程的三个概念：原子性、可见性、有序性、
 *      原子性：即一个操作或者多个操作 要么都执行并且保证执行的过程不会被打断、要不就都不执行；
 *      可见性：多个线程访问同一个变量时，一个线程修改了这个变量的值，其他线程能立即看到修改的量；
 *      有序性：程序执行的顺序按照代码的顺序执行。
 *
 * 指令重排：处理器为提高效率，会对代码的执行顺序重新排列，它能保证重排之后的执行结果与原顺序执行相同。
 *               ---重排会考虑到数据依赖性，如果语句2需要依赖于语句1的结果，那么1一定在2前面执行。
 */
public class SyncLazy {

    /**
     * 创建对象过程：
     *      1.分配内存空间
     *      2.执行构造方法，初始化对象
     *      3.把对象指向内存空间
     *
     *      多线程下：发生指令重排，如线程1执行顺序为132，线程1正常，线程2再来会拿到一个空的内存。
     *      volatile ： 避免指令重排
     */
    private volatile static SyncLazy SYNCLAZY;

    private SyncLazy(){

    }

    private static SyncLazy getInstance(){
        if(SYNCLAZY == null){
            synchronized (SyncLazy.class){
                if(SYNCLAZY == null){
                    SYNCLAZY = new SyncLazy();
                }
            }
        }
        return SYNCLAZY;
    }




}
